// C
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string>
#include <math.h>
#include <time.h>
#include <ctype.h>

// C++
#include <iostream>
#include <fstream>
#include <chrono>
#include <string>
#include <thread>

#include <cmath>
#include <vector>
#include <map>
#include <set>

#include "dds/dds.h"

#include "../../../../include/log_client/LogClient.h"

// 接收的idl
{% for element in input_idl_module_path_list %}
#include "{{element}}"
{% endfor %}
// 发送的idl
{% for element in output_idl_module_path_list %}
#include "{{element}}"
{% endfor %}
// 微服务的库 和 自己的idl
#include "../../../atomic_service/{{service_info["name"]}}/atomic_include/{{service_info["name"]}}.h"
#include "../../../atomic_service/{{service_info["name"]}}/idl/{{service_info["name"]}}.h"

// 全局数据结构，存储每个Topic的最新消息
struct GlobalData
{
    {% for element in global_data_list %}
    // {{element[1]}} 服务的 {{element[2]}} 方法的数据
    {{element[1]}}_{{element[3]}} {{element[1]}}_{{element[0]}}_data;
    int {{element[1]}}_{{element[0]}}_state =0;
    {% endfor %}
} global_data;

{% for element in global_data_list %}
// 订阅{{element[1]}} 服务的 {{element[2]}} 方法的线程函数
void {{element[1]}}_{{element[0]}}_{{element[2]}}_subscriber(dds_entity_t participant)
{
    dds_entity_t topic;
    dds_entity_t reader;
    dds_return_t rc;

    // 创建Topic
    topic = dds_create_topic(participant, &{{element[1]}}_{{element[3]}}_desc,
                             "{{element[1]}}_{{element[0]}}_{{element[2]}}_topic", NULL, NULL);
    if (topic < 0)
    {
        std::cerr << "ERROR: {{element[1]}}_{{element[0]}}_{{element[2]}}_topic -- Failed to create topic: " << dds_strretcode(-topic) << std::endl;
        LogClient::getInstance().logError("ERROR: {{element[1]}}_{{element[0]}}_{{element[2]}}_topic -- Failed to create topic: " + std::string(dds_strretcode(-topic)));
        return ;
    }

    // 创建读取器
    dds_qos_t *qos = dds_create_qos();
    dds_qset_reliability(qos, DDS_RELIABILITY_RELIABLE, DDS_SECS(10));
    dds_qset_history(qos, DDS_HISTORY_KEEP_LAST, 10);

    reader = dds_create_reader(participant, topic, qos, NULL);
    if (reader < 0)
    {
        std::cerr << "ERROR: {{element[1]}}_{{element[0]}}_{{element[2]}}_topic -- Failed to create reader: " << dds_strretcode(-reader) << std::endl;
        LogClient::getInstance().logError("ERROR: {{element[1]}}_{{element[0]}}_{{element[2]}}_topic -- Failed to create reader: " + std::string(dds_strretcode(-reader)));
        dds_delete(topic);
        dds_delete_qos(qos);
        return ;
    }
    dds_delete_qos(qos);

    std::cout << "{{element[1]}}_{{element[0]}}_{{element[2]}}_topic subscriber ready" << std::endl;
    LogClient::getInstance().logInfo("{{element[1]}}_{{element[0]}}_{{element[2]}}_topic subscriber ready");

    void *samples[1];
    dds_sample_info_t infos[1];
    // 为sample分配空间
    for (int i = 0; i < 1; i++)
    {
        samples[i] = {{element[1]}}_{{element[3]}}__alloc();
    }

    while (true)
    {
        // 阻塞读取数据
        rc = dds_take(reader, samples, infos, 1, 1);
        if (rc < 0)
        {
            std::cerr << "Error: {{element[1]}}_{{element[0]}}_{{element[2]}}_topic -- Error reading: " << dds_strretcode(-rc) << std::endl;
            LogClient::getInstance().logError("ERROR: {{element[1]}}_{{element[0]}}_{{element[2]}}_topic -- Error reading: " + std::string(dds_strretcode(-rc)));
            dds_sleepfor(DDS_MSECS(50));
            continue;
        }
        else if (rc == 0)
        {
            dds_sleepfor(DDS_MSECS(50));
            continue; // 无数据可用
        }

        if (infos[0].valid_data && samples[0] != NULL)
        {
            //{{element[1]}}_{{element[3]}} *{{element[1]}}_{{element[0]}}_data = ({{element[1]}}_{{element[3]}} *)samples[0];
            global_data.{{element[1]}}_{{element[0]}}_data = *({{element[1]}}_{{element[3]}} *)samples[0];
            global_data.{{element[1]}}_{{element[0]}}_state = 1;
        }
        else
        {
        /* Polling sleep. */
        dds_sleepfor(DDS_MSECS(50));
        }
    }
    // 释放样本内存
    {{element[1]}}_{{element[3]}}_free(samples[0], DDS_FREE_ALL);

    // 清理资源
    dds_delete(reader);
    dds_delete(topic);
}
{% endfor %}

int main(int argc, char *argv[])
{
    // 初始化日志客户端
    LogClient::getInstance().init("{{orchestrattion_name}}", "{{service_info["name"]}}_{{service_info["id"]}}");

    dds_entity_t participant;
    dds_entity_t topic;
    dds_entity_t writer;
    dds_return_t rc;

    // 1. 创建域参与者
    participant = dds_create_participant(0, NULL, NULL);
    if (participant < 0)
    {
        std::cerr << "ERROR: Failed to create participant: " << dds_strretcode(-participant) << std::endl;
        LogClient::getInstance().logError("ERROR: Failed to create participant: " + std::string(dds_strretcode(-participant)));
        return EXIT_FAILURE;
    }

    std::cout << "{{service_info["type"]}}_{{service_info["name"]}}_{{service_info["id"]}} starting..." << std::endl;
    LogClient::getInstance().logInfo("{{service_info["type"]}}_{{service_info["name"]}}_{{service_info["id"]}} starting...");

    // 2. 创建订阅线程
    {% for element in global_data_list %}
    std::thread {{element[1]}}_{{element[0]}}_{{element[2]}}_thread({{element[1]}}_{{element[0]}}_{{element[2]}}_subscriber, participant);
    {% endfor %}

    std::cout << "All subscribers initialized. Starting main loop..." << std::endl;

    // 3. 创建 发布 Topic 类型
    topic = dds_create_topic(participant, &{{service_info["name"]}}_{{service_output_struct["name"]}}_desc, "{{service_info["name"]}}_{{service_info["id"]}}_{{service_info["method"]}}_topic", NULL, NULL);
    if (topic < 0)
    {
        std::cerr << "ERROR: {{service_info["name"]}}_{{service_info["id"]}}_{{service_info["method"]}}_topic -- Failed to create topic: " << dds_strretcode(-topic) << std::endl;
        LogClient::getInstance().logError("{{service_info["name"]}}_{{service_info["id"]}}_{{service_info["method"]}}_topic -- Failed to create topic: " + std::string(dds_strretcode(-topic)));
        return EXIT_FAILURE;
    }

    // 4. 创建 发布 Writer 类型
    writer = dds_create_writer(participant, topic, NULL, NULL);
    if (writer < 0) {
        std::cerr << "Error: Failed to create writer: " << dds_strretcode(-writer) << std::endl;
        LogClient::getInstance().logError("Error: Failed to create writer: " + std::string(dds_strretcode(-writer)));
        dds_delete(topic);
        dds_delete(participant);
        return EXIT_FAILURE;
    }

    // 定义变量
    // 服务的函数输入输出变量
    {{service_info["name"]}}::{{service_input_struct["name"]}} input;
    {{service_info["name"]}}::{{service_output_struct["name"]}} output;
    // dds的服务函数输出变量
    {{service_info["name"]}}_{{service_output_struct["name"]}} publisher_data;

    // 4. 主循环 - 每50ms打印一次最新数据
    while (true)
    {
        // 设置一个标志位flag，0表示没有服务更新消息
        {% if global_data_list == []%}
        int flag = 1;
        {% else %}
        int flag = 0;
        {% endif %}

        // 只要有一个服务更新了消息，就运行代码
        {% for element in global_data_list %}
        if(global_data.{{element[1]}}_{{element[0]}}_state == 1){
            // 给输入值赋值
            {% for input_assignment in input_assignment_list_dict[element[0]] %}
            input.{{input_assignment[1]}} = global_data.{{node_id_service_dict[input_assignment[2]]["name"]}}_{{input_assignment[2]}}_data.{{input_assignment[0]}};
            {% endfor %}

            // 将状态值置为0
            global_data.{{element[1]}}_{{element[0]}}_state = 0;
            flag = 1;
        }
        {% endfor %}

        if(flag == 1){
            flag = 0;
            //调用服务
            //打印输入值
            LogClient::getInstance().logInfo("input: " + {{service_info["name"]}}::toString(input));

            // 服务计算
            {{service_info["name"]}}::{{service_info["method"]}}(&input, &output);

            //打印输出值
            LogClient::getInstance().logInfo("output: " + {{service_info["name"]}}::toString(output));

            // 给输出值赋值
            {% for element in output_struct_var_list %}
            {% if element[2] == "string" %}
            publisher_data.{{element[0]}} = dds_string_dup(output.{{element[0]}}.c_str());
            {% else %}
            publisher_data.{{element[0]}} = output.{{element[0]}};
            {% endif %}
            {% endfor %}

            // 发布数据
            rc = dds_write(writer, &publisher_data);
            if (rc != DDS_RETCODE_OK){
                std::cout << "ERROR: Failed to write {{service_info["name"]}}_{{service_info["id"]}}_{{service_info["method"]}}_topic: " << dds_strretcode(-rc) << std::endl;
                LogClient::getInstance().logError("ERROR: Failed to write {{service_info["name"]}}_{{service_info["id"]}}_{{service_info["method"]}}_topic: " + std::string(dds_strretcode(-rc)));
            }else{
                std::cout << "SUCCESS: Published {{service_info["name"]}}_{{service_info["id"]}}_{{service_info["method"]}}_topic" << std::endl;
                LogClient::getInstance().logInfo("SUCCESS: Published {{service_info["name"]}}_{{service_info["id"]}}_{{service_info["method"]}}_topic");
            }
            {% if global_data_list != []%}
            continue;
            {% endif %}
        }
        // 休眠50ms
        dds_sleepfor(DDS_MSECS(50));
    }

    // 理论上不会执行到这里
    {% for element in global_data_list %}
    {{element[1]}}_{{element[0]}}_{{element[2]}}_thread.join();
    {% endfor %}

    dds_delete(participant);
    return EXIT_SUCCESS;
}